#include <htc.h>;
#include <delays.h>;
#include <timers.h>;
#include <i2c.h>
#include <usart.h>

#define OUTPUT 0
#define INPUT 1

/* I2C */
#define		CNTRL_BYTE_SRAM_RTCC					0b11011110
#define		CNTRL_BYTE_EEPROM_RTCC					0b10101110
#define		SRAM_BLOCK_SIZE							64
#define		SRAM_BLOCK_START_ADD					0x20
#define		EEPROM_PAGE_SIZE						8
#define		UNIQUE_ID_START_ADD						0xF0

#define		RTCC_SEC_REG							0x00
#define		RTCC_MIN_REG							0x01
#define		RTCC_HOUR_REG							0x02
#define		RTCC_DAY_REG							0x03
#define		RTCC_DATE_REG							0x04
#define		RTCC_MONTH_REG							0x05
#define		RTCC_YEAR_REG							0x06
#define		RTCC_CNTRL_REG							0x07
#define		RTCC_CAL_REG							0x08
#define		RTCC_UNLOCK_REG							0x09
#define		RTCC_ALARM0_SEC_REG						0x0A
#define		RTCC_ALARM0_MIN_REG						0x0B
#define		RTCC_ALARM0_HOUR_REG					0x0C
#define		RTCC_ALARM0_DAY_REG						0x0D
#define		RTCC_ALARM0_DATE_REG					0x0E
#define		RTCC_ALARM0_MONTH_REG					0x0F
#define		RTCC_ALARM1_SEC_REG						0x11	
#define		RTCC_ALARM1_MIN_REG						0x12
#define		RTCC_ALARM1_HOUR_REG					0x13
#define		RTCC_ALARM1_DAY_REG						0x14
#define		RTCC_ALARM1_DATE_REG					0x15
#define		RTCC_ALARM1_MONTH_REG					0x16
#define		RTCC_VCC_FAIL_MIN_REG					0x18
#define		RTCC_VCC_FAIL_HOUR_REG					0x19
#define		RTCC_VCC_FAIL_DATE_REG					0x1A
#define		RTCC_VCC_FAIL_DAY_MONTH_REG				0x1B
#define		RTCC_VCC_RESTORE_MIN_REG				0x1C
#define		RTCC_VCC_RESTORE_HOUR_REG				0x1D
#define		RTCC_VCC_RESTORE_DATE_REG				0x1E
#define		RTCC_VCC_RESTORE_DAY_MONTH_REG			0x1F

#define		RTCC_EN_OSC_START						0x80
#define		RTCC_EN_12_24							0x40
#define		RTCC_EN_VBATEN							0x08
#define		RTCC_EN_VBAT							0x10
#define		RTCC_EN_OSCON							0x20
#define		RTCC_EN_LP								0x20
#define		RTCC_EN_RS0								0x01
#define		RTCC_EN_RS1								0x02
#define		RTCC_EN_RS2								0x04
#define		RTCC_EN_EXTOSC							0x08
#define		RTCC_EN_ALM0							0x10
#define		RTCC_EN_ALM1							0x20
#define		RTCC_EN_SQWE							0x40
#define		RTCC_EN_OUT								0x80

#define		RTCC_EN_ALARM_SEC_MATCH					0x00
#define		RTCC_EN_ALARM_MIN_MATCH					0x10
#define		RTCC_EN_ALARM_HOUR_MATCH				0x20
#define		RTCC_EN_ALARM_DAY_MATCH					0x30
#define		RTCC_EN_ALARM_DATE_MATCH				0x40
#define		RTCC_EN_ALARM_TIMESTAMP_MATCH			0x70

#define		RTCC_MFP_1HZ							0x00
#define		RTCC_MFP_4096HZ							0x01
#define		RTCC_MFP_8192HZ							0x02
#define		RTCC_MFP_32768HZ						0x03
#define		RTCC_CAL_ENABLE							0x10;	

typedef struct{
	unsigned char Day;
	unsigned char Sec;
	unsigned char Min;
	unsigned char Hour;
	unsigned char Date;
	unsigned char Month;
	unsigned char Year;
}RTCCTimeDate;


void config (void)
{
	unsigned char config;
	unsigned int spbrg ;
	unsigned char Temp = 0;
	unsigned char sync_mode ;
	unsigned char slew ;
	
	PORTE = OUTPUT;
	LATE = 0;
	TRISE = 0;
	/* open usart prend config et spbrg comme parametre */
	/* config */
	config = USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ADDEN_OFF & USART_BRGH_LOW & USART_CONT_RX & USART_SYNC_MASTER & USART_EIGHT_BIT & USART_ASYNCH_MODE & BAUD_IDLE_CLK_LOW & BAUD_8_BIT_RATE & BAUD_WAKEUP_OFF & BAUD_AUTO_OFF;
	
	/* spbrg */
	spbrg = 40;
	Open1USART ( config , spbrg ) ;
	
	/* I2C */
	/* disable interrupt */
	DisableIntI2C1 ;
	
	/*  unsigned char sync_mode,  unsigned char slew */
	sync_mode = MASTER ; 	/* I2C Master mode */
	slew = SLEW_ON; 		/* Slew rate enabled for 400kHz mode  */
	OpenI2C ( sync_mode , slew ) ;
	SSP1ADD = 15;	
}

void WRITE_I2C(unsigned char Slave_Add,unsigned char Add, unsigned char Val)
{
	IdleI2C1();
	SEN = 1;									//Initiate Start condition on I2C bus
	while(SEN);									//Wait for Start condition to complete
	SSPBUF = Slave_Add;
	IdleI2C1();
	while(ACKSTAT);     						//Check for ACK from I2C slave device

	SSPBUF = Add;		
	IdleI2C1();
	while(ACKSTAT);      						//Check for ACK from I2C slave device

	SSPBUF = Val;		
	IdleI2C1();
	while(ACKSTAT);      						//Check for ACK from I2C slave device
	
	PEN = 1;			   						//Issue stop condition
	
}

unsigned char READ_I2C(unsigned char Slave_Add,unsigned char Add)
{
	unsigned char Ret_Val;
	IdleI2C1();
	SEN = 1;									//Initiate Start condition on I2C bus
	while(SEN);									//Wait for Start condition to complete
	SSPBUF = Slave_Add;
	IdleI2C1();
	while(ACKSTAT);      						//Check for ACK from I2C slave device
	
	SSPBUF = Add;								//Place address to be read from I2C slave device
	IdleI2C1();	
	while(ACKSTAT);      						//Check for ACK from I2C slave device
	
	Slave_Add = Slave_Add | 0x01;				//I2C Read operation
	RSEN = 1;									//Initiate Restart condition on I2C bus
	while(RSEN);								//Wait for Restart condition to complete
	
	SSPBUF = Slave_Add;
	IdleI2C1();
	while(ACKSTAT);      						//Check for ACK from I2C slave device
	
	RCEN =1;									//Prepare I2C master device for recepetion
	while(RCEN);								//Wait until read operation is completed
	//while ( !SSP1STATbits.BF );     			 // wait until byte received  
	
	Ret_Val = SSPBUF;
	ACKDT = 1;
	ACKEN = 1;
	while(ACKEN);
	PEN = 1;									//Issue stop condition
	
	return(Ret_Val);
}
void InitRTCC(void)
{
	unsigned char Temp = 0;
	WRITE_I2C(CNTRL_BYTE_SRAM_RTCC, RTCC_CNTRL_REG, \
	RTCC_EN_SQWE | \
	RTCC_MFP_1HZ );
	
	Temp = READ_I2C(CNTRL_BYTE_SRAM_RTCC,RTCC_SEC_REG);
	
	if(!(Temp & 0x80))
	{
		//Oscilator bit of RTCC is off. Turn on to start RTCC function
		WRITE_I2C(CNTRL_BYTE_SRAM_RTCC, RTCC_SEC_REG, RTCC_EN_OSC_START);
		PORTE = 1;
	}
}

void ReadRTCCTimeDate(RTCCTimeDate* ptrToUserVal) {
	ptrToUserVal->Sec 	= ( READ_I2C(CNTRL_BYTE_SRAM_RTCC,RTCC_SEC_REG) & 0x7F ); 
	ptrToUserVal->Min 	=   READ_I2C(CNTRL_BYTE_SRAM_RTCC,RTCC_MIN_REG);
	ptrToUserVal->Hour 	= ( READ_I2C(CNTRL_BYTE_SRAM_RTCC,RTCC_HOUR_REG) & 0x3F );
	
	ptrToUserVal->Day 	= ( READ_I2C(CNTRL_BYTE_SRAM_RTCC,RTCC_DAY_REG) & 0x7 ) ;
	ptrToUserVal->Date 	= ( READ_I2C(CNTRL_BYTE_SRAM_RTCC,RTCC_DATE_REG) & 0x3F ); 
	ptrToUserVal->Month = ( READ_I2C(CNTRL_BYTE_SRAM_RTCC,RTCC_MONTH_REG) & 0x1F );
	ptrToUserVal->Year 	=   READ_I2C(CNTRL_BYTE_SRAM_RTCC,RTCC_YEAR_REG) ;
}

void WriteTimeDateOnUART_HEX ( RTCCTimeDate* ptrToUserVal )
{
	/* Date */
	while ((!TXSTA1bits.TRMT)); 
	Write1USART ( ptrToUserVal->Day );
	while ((!TXSTA1bits.TRMT)); 
	Write1USART ( ptrToUserVal->Date );
	while ((!TXSTA1bits.TRMT)); 
	Write1USART ( ptrToUserVal->Month );
	while ((!TXSTA1bits.TRMT)); 
	Write1USART ( ptrToUserVal->Year );

	/* Heure */
	while ((!TXSTA1bits.TRMT)); 
	Write1USART ( ptrToUserVal->Hour );
	while ((!TXSTA1bits.TRMT)); 
	Write1USART ( ptrToUserVal->Min );
	while ((!TXSTA1bits.TRMT)); 
	Write1USART ( ptrToUserVal->Sec );
}

void configRTC( void )
{
	unsigned char seconde;
	unsigned char minute ;
	unsigned char heure ;
	unsigned char wkday ;
	unsigned char date ;
	unsigned char month ;
	unsigned char year ;
	
	/* seconde & start oscillator*/
	seconde = 0x00 | 0x80; // 0 seconde
	WRITE_I2C ( CNTRL_BYTE_SRAM_RTCC , RTCC_SEC_REG , seconde );
	
	/* minute */
	minute = 0x19; // 4 minutes 
	WRITE_I2C ( CNTRL_BYTE_SRAM_RTCC , RTCC_MIN_REG , minute );
	
	/* heure & mode 24*/
	heure = 0x22 | 0x0 ;
	WRITE_I2C ( CNTRL_BYTE_SRAM_RTCC , RTCC_HOUR_REG , heure );
	
	/* wk day & VBATEN & Pwrfail & oscrun */
	wkday = 0x3 | 0x8 | 0x0 | 0x20;
	WRITE_I2C ( CNTRL_BYTE_SRAM_RTCC , RTCC_DAY_REG , wkday );
	
	/* date */
	date = 0x26 ;
	WRITE_I2C ( CNTRL_BYTE_SRAM_RTCC , RTCC_DATE_REG , date );
	
	/* month & lpyr */
	month = 0x08 | 0x0 ;
	WRITE_I2C ( CNTRL_BYTE_SRAM_RTCC , RTCC_MONTH_REG , month );
	
	/* year */
	year = 0x14 ;
	WRITE_I2C ( CNTRL_BYTE_SRAM_RTCC , RTCC_YEAR_REG , year );
	
}

int main (void) {
	unsigned char busy;
	unsigned char control ;
	unsigned char I2C_address;
	unsigned char rdptr;
	unsigned char length ;
	RTCCTimeDate ptrToUserVal;
	
	config();
	/* I2C */
	//control = 0b11011110 ;/* for RTC read 0b11011111: for RTC write : 0b11011110 */
	//I2C_address = 0x00;
	//length = 1;
	
	busy = Busy1USART ();
		if ( busy ){
			PORTE = 0xF;
			Delay1KTCYx(1000);
			DataRdy1USART () ;
		}
		else {
			PORTE = 0x0;
			Delay1KTCYx(1000);
	//		Write1USART ( 'A' );
		}
	
	//InitRTCC ();
	//configRTC();
	
	/* lire date */
	//ReadRTCCTimeDate ( &ptrToUserVal );
	//WriteTimeDateOnUART_HEX  ( &ptrToUserVal );
	rdptr =  READ_I2C ( CNTRL_BYTE_SRAM_RTCC,RTCC_DAY_REG ) ;
	Write1USART ( rdptr );
	while ( 1 ){
		Delay10KTCYx(0xFF);
		ReadRTCCTimeDate ( &ptrToUserVal );
		WriteTimeDateOnUART_HEX  ( &ptrToUserVal );
	}
}


	/*  unsigned char control, unsigned char address, unsigned char *rdptr, unsigned char length */

		// StartI2C ();
		// WriteI2C1 ( control ) ;
		// IdleI2C1();
		// WriteI2C1 ( I2C_address );
		// IdleI2C1();
		
		// RestartI2C1();
		// WriteI2C1 ( control + 1 ) ;
		// rdptr = ReadI2C1 ();
		// Write1USART ( rdptr );
		// AckI2C1 ();
		// rdptr = ReadI2C1 ();
		// Write1USART ( rdptr );
		// AckI2C1 ();
		// rdptr = ReadI2C1 ();
		// Write1USART ( rdptr );
		// //AckI2C1 ();
		// StopI2C1 ();
		// //CloseI2C1 ();
		
		//EESequentialRead ( control , I2C_address , &rdptr , length );
	/* 	busy = Busy1USART ();
		if ( busy ){
			PORTE = 0xF;
			Delay1KTCYx(1000);
			DataRdy1USART () ;
		}
		else {
			PORTE = 0x0;
			Delay1KTCYx(1000);
			Write1USART ( rdptr );
		} */
		